<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mirror Flowers</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Cinzel+Decorative:wght@700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>
    <link href="/static/styles.css" rel="stylesheet">
    <style>
        :root {
            --bg-color: #ffffff;
            --text-color: #212529;
            --card-bg: #ffffff;
            --border-color: #dee2e6;
            --custom-file-bg: #f8f9fa;
            --custom-file-border: #ddd;
            --custom-file-hover-bg: #f1f8ff;
            --custom-file-hover-border: #0d6efd;
            --pre-bg: #f8f9fa;
            --pre-color: #212529;
        }
        
        [data-theme="dark"] {
            --bg-color: #212529;
            --text-color: #f8f9fa;
            --card-bg: #343a40;
            --border-color: #495057;
            --custom-file-bg: #2b3035;
            --custom-file-border: #495057;
            --custom-file-hover-bg: #3d4247;
            --custom-file-hover-border: #0d6efd;
            --pre-bg: #2b3035;
            --pre-color: #f8f9fa;
        }
        
        body {
            background-color: var(--bg-color);
            color: var(--text-color);
            transition: all 0.3s ease;
        }
        
        .card {
            background-color: var(--card-bg);
            border-color: var(--border-color);
        }
        
        .card-header {
            background-color: var(--card-bg);
            border-bottom-color: var(--border-color);
        }
        
        .container { max-width: 1200px; margin-top: 2rem; }
        .result-card { 
            margin: 1rem 0; 
            padding: 1rem; 
            border-radius: 8px; 
            background-color: var(--card-bg);
            border: 1px solid var(--border-color);
        }
        .loading { text-align: center; margin: 2rem 0; }
        .file-list { margin-top: 1rem; }
        .file-list-item { padding: 0.5rem; border-bottom: 1px solid #eee; }
        .file-list-item:last-child { border-bottom: none; }
        pre { 
            white-space: pre-wrap; 
            word-wrap: break-word; 
            max-height: 400px; 
            overflow-y: auto;
            background-color: var(--pre-bg) !important;
            color: var(--pre-color) !important;
            border: 1px solid var(--border-color);
            padding: 1rem;
        }
        .btn-link { text-decoration: none; }
        .collapse { transition: all 0.3s ease; }
        .upload-container {
            position: relative;
            min-height: 100px;
            margin-bottom: 1rem;
        }
        .upload-section {
            width: 100%;
            transition: all 0.3s ease;
        }
        .upload-section input[type="file"] {
            display: block !important;
            opacity: 1 !important;
            position: relative !important;
            width: 100%;
        }
        .custom-file-upload {
            border: 2px dashed var(--custom-file-border);
            border-radius: 8px;
            padding: 20px;
            text-align: center;
            background: var(--custom-file-bg);
            transition: all 0.3s ease;
        }
        .custom-file-upload:hover {
            border-color: var(--custom-file-hover-border);
            background: var(--custom-file-hover-bg);
        }
        .form-label {
            margin-bottom: 10px;
            color: #666;
        }
        .file-list {
            margin-top: 1rem;
            max-height: 200px;
            overflow-y: auto;
        }
        .file-list-item {
            padding: 8px;
            border-bottom: 1px solid #eee;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .file-list-item:last-child {
            border-bottom: none;
        }
        .progress {
            background-color: #e9ecef;
            border-radius: 0.25rem;
            box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
        }
        
        .progress-bar {
            display: flex;
            flex-direction: column;
            justify-content: center;
            color: #fff;
            text-align: center;
            background-color: #007bff;
            transition: width .6s ease;
        }
        
        .progress-bar-striped {
            background-image: linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);
            background-size: 1rem 1rem;
        }
        
        .progress-bar-animated {
            animation: progress-bar-stripes 1s linear infinite;
        }
        
        @keyframes progress-bar-stripes {
            from { background-position: 1rem 0; }
            to { background-position: 0 0; }
        }
        
        /* 主题切换按钮样式 */
        .theme-toggle {
            position: fixed;
            top: 1rem;
            right: 1rem;
            padding: 0.5rem;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            background-color: var(--card-bg);
            border: 1px solid var(--border-color);
            color: var(--text-color);
            transition: all 0.3s ease;
        }
        
        .theme-toggle:hover {
            background-color: var(--custom-file-hover-bg);
        }

        .vulnerability-item {
            background-color: var(--card-bg);
            border-color: var(--border-color) !important;
        }

        .list-group-item {
            background-color: var(--card-bg);
            border-color: var(--border-color);
            color: var(--text-color);
        }

        .text-muted {
            color: #6c757d !important;
        }

        [data-theme="dark"] .text-muted {
            color: #adb5bd !important;
        }

        .title-container {
            text-align: center;
            margin-bottom: 2rem;
            padding: 2rem 0;
        }
        
        .main-title {
            font-family: 'Cinzel Decorative', cursive;
            font-size: 3rem;
            background: linear-gradient(45deg, #1a1a1a, #4a4a4a);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            margin-bottom: 0.5rem;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
        }
        
        [data-theme="dark"] .main-title {
            background: linear-gradient(45deg, #ffffff, #cccccc);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        
        .subtitle {
            font-family: "Microsoft YaHei", sans-serif;
            color: var(--text-color);
            font-size: 1.2rem;
            opacity: 0.8;
        }
    </style>
</head>
<body>
    <button class="theme-toggle" onclick="toggleTheme()" title="切换主题">
        <i class="bi bi-moon-fill" id="themeIcon"></i>
    </button>
    <div class="container">
        <div class="title-container">
            <h1 class="main-title">Mirror Flowers</h1>
            <div class="subtitle">镜花 · 代码安全审计工具</div>
        </div>
        
        <!-- API配置部分 -->
        <div class="card mb-4">
            <div class="card-header">
                <h5 class="mb-0">API配置</h5>
            </div>
            <div class="card-body">
                <div class="row g-3">
                    <div class="col-md-4">
                        <input type="text" id="apiKey" class="form-control" placeholder="OpenAI API Key">
                    </div>
                    <div class="col-md-4">
                        <input type="text" id="apiBase" class="form-control" placeholder="API Base URL（可选）">
                    </div>
                    <div class="col-md-2">
                        <select id="modelSelect" class="form-select">
                            <option value="">选择模型</option>
                        </select>
                    </div>
                    <div class="col-md-2">
                        <button onclick="updateConfig()" class="btn btn-primary w-100">更新配置</button>
                    </div>
                </div>
            </div>
        </div>

        <!-- 文件上传部分 -->
        <div class="card mb-4">
            <div class="card-header">
                <h5 class="mb-0">代码审计</h5>
            </div>
            <div class="card-body">
                <div class="mb-3">
                    <select id="uploadType" class="form-select mb-3">
                        <option value="single">单文件审计</option>
                        <option value="folder">项目文件夹审计</option>
                    </select>
                </div>
                
                <div class="mb-3">
                    <label for="projectType" class="form-label">项目类型</label>
                    <select class="form-control" id="projectType">
                        <option value="auto">自动检测</option>
                        <option value="php">PHP项目</option>
                        <option value="python">Python项目</option>
                        <option value="java">Java项目</option>
                        <option value="javascript">JavaScript项目</option>
                    </select>
                </div>
                
                <div class="upload-container">
                    <!-- 单文件上传 -->
                    <div id="singleFileUpload" class="upload-section">
                        <div class="custom-file-upload">
                            <label for="codeFile" class="form-label">选择文件 (.php, .java, .js, .py)</label>
                            <input type="file" id="codeFile" class="form-control" accept=".php,.java,.js,.py">
                        </div>
                        <div id="singleFileList" class="file-list mt-2"></div>
                    </div>
                    
                    <!-- 文件夹上传 -->
                    <div id="folderUpload" class="upload-section" style="display: none;">
                        <div class="custom-file-upload">
                            <label for="codeFolder" class="form-label">选择项目文件夹</label>
                            <input type="file" id="codeFolder" class="form-control" webkitdirectory directory>
                        </div>
                        <div id="folderFileList" class="file-list mt-2"></div>
                    </div>
                </div>
                
                <button onclick="startAudit()" id="auditBtn" class="btn btn-success mt-3" disabled>
                    开始审计
                </button>
            </div>
        </div>

        <!-- 结果显示部分 -->
        <div id="results" style="display: none;">
            <h2>审计结果</h2>
            <div class="accordion" id="auditResults">
                <!-- 结果将动态添加到这里 -->
            </div>
        </div>

        <!-- 加载提示 -->
        <div id="loading" class="loading" style="display: none;">
            <div class="spinner-border text-primary" role="status">
                <span class="visually-hidden">分析中...</span>
            </div>
            <div class="mt-3">
                <p id="loadingText" class="mb-2">代码分析中，请稍候...</p>
                <div class="progress" style="height: 20px; width: 300px; margin: 0 auto;">
                    <div id="progressBar" class="progress-bar progress-bar-striped progress-bar-animated" 
                         role="progressbar" style="width: 0%;" 
                         aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
                </div>
                <p id="currentFile" class="mt-2 text-muted small"></p>
            </div>
        </div>
    </div>

    <script>
        const apiUrl = 'http://127.0.0.1:8000';

        // 获取可用模型列表
        async function fetchAvailableModels() {
            try {
                const response = await fetch(`${apiUrl}/api/models`);
                if (response.ok) {
                    const data = await response.json();
                    console.log('获取到的模型数据:', data);
                    
                    const modelSelect = document.getElementById('modelSelect');
                    modelSelect.innerHTML = '<option value="">选择模型</option>';
                    
                    if (data.models && typeof data.models === 'object') {
                        // 遍历每个模型类别
                        Object.entries(data.models).forEach(([category, models]) => {
                            if (models.length > 0) {
                                const optgroup = document.createElement('optgroup');
                                optgroup.label = category;
                                
                                // 对模型进行排序
                                const sortedModels = [...models].sort((a, b) => {
                                    // 将Pro模型排在后面
                                    const aIsPro = a.startsWith('Pro/');
                                    const bIsPro = b.startsWith('Pro/');
                                    if (aIsPro && !bIsPro) return 1;
                                    if (!aIsPro && bIsPro) return -1;
                                    return a.localeCompare(b);
                                });

                                sortedModels.forEach(model => {
                                    const option = document.createElement('option');
                                    option.value = model;
                                    // 美化显示名称
                                    option.textContent = model.split('/').pop() || model;
                                    if (model === data.current_model) {
                                        option.selected = true;
                                    }
                                    optgroup.appendChild(option);
                                });
                                
                                modelSelect.appendChild(optgroup);
                            }
                        });

                        // 如果没有选中的模型，默认选择第一个GPT模型
                        if (!modelSelect.value && data.models.GPT?.length > 0) {
                            modelSelect.value = data.models.GPT[0];
                        }
                    } else {
                        console.error('模型数据格式错误:', data);
                    }
                } else {
                    const error = await response.json();
                    console.error('获取模型列表失败:', error);
                }
            } catch (error) {
                console.error('获取模型列表失败:', error);
            }
        }

        // 更新配置函数
        async function updateConfig() {
            const apiKey = document.getElementById('apiKey').value;
            let apiBase = document.getElementById('apiBase').value;
            const modelSelect = document.getElementById('modelSelect');
            const model = modelSelect.value || modelSelect.options[1]?.value; // 如果没有选择，使用第一个有效选项

            if (!apiKey) {
                alert('请输入 API Key');
                return;
            }

            // 规范化 API 基础 URL
            if (apiBase) {
                apiBase = apiBase.trim();
                if (!apiBase.startsWith('http')) {
                    apiBase = 'https://' + apiBase;
                }
                if (!apiBase.endsWith('/v1')) {
                    apiBase = apiBase.replace(/\/+$/, '') + '/v1';
                }
            }

            try {
                console.log('发送配置:', { api_key: apiKey, api_base: apiBase, model });  // 添加调试日志
                
                const response = await fetch(`${apiUrl}/api/configure`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        api_key: apiKey,
                        api_base: apiBase || null,
                        model: model || null
                    })
                });

                if (response.ok) {
                    const result = await response.json();
                    console.log('配置更新结果:', result);  // 添加调试日志
                    alert(result.message);
                    await fetchAvailableModels();
                } else {
                    const error = await response.json();
                    throw new Error(error.detail || '配置更新失败');
                }
            } catch (error) {
                console.error('配置更新失败:', error);
                alert('配置更新失败: ' + error.message);
            }
        }

        // 初始化上传类型切换
        function initializeUploadTypes() {
            const uploadType = document.getElementById('uploadType');
            const sections = {
                single: document.getElementById('singleFileUpload'),
                folder: document.getElementById('folderUpload')
            };
            
            // 确保初始状态正确
            sections.single.style.display = 'block';
            sections.folder.style.display = 'none';
            
            uploadType.addEventListener('change', function() {
                // 使用简单的显示/隐藏切换
                Object.entries(sections).forEach(([type, section]) => {
                    section.style.display = type === this.value ? 'block' : 'none';
                    
                    // 如果是隐藏的部分，清除其文件选择
                    if (type !== this.value) {
                        const input = section.querySelector('input[type="file"]');
                        if (input) {
                            input.value = '';
                        }
                        const fileList = section.querySelector('.file-list');
                        if (fileList) {
                            fileList.innerHTML = '';
                        }
                    }
                });
                
                // 更新按钮状态
                updateAuditButtonState();
            });
        }

        // 修改文件输入监听器
        function initializeFileInputs() {
            const fileInputs = {
                'codeFile': 'singleFileList',
                'codeFolder': 'folderFileList'
            };
            
            Object.entries(fileInputs).forEach(([inputId, listId]) => {
                const input = document.getElementById(inputId);
                if (input) {
                    input.addEventListener('change', function() {
                        if (this.files && this.files.length > 0) {
                            updateFileList(this.files, listId);
                            document.getElementById('auditBtn').disabled = false;
                        } else {
                            document.getElementById(listId).innerHTML = '';
                            document.getElementById('auditBtn').disabled = true;
                        }
                    });
                }
            });
        }

        // 页面加载时初始化
        document.addEventListener('DOMContentLoaded', function() {
            initTheme();
            initializeUploadTypes();
            initializeFileInputs();
            fetchAvailableModels();
        });

        // API Base URL 改变时更新模型列表
        document.getElementById('apiBase').addEventListener('change', async (event) => {
            console.log('API Base URL changed:', event.target.value);
            await fetchAvailableModels();
        });

        // 更新文件列表显示
        function updateFileList(files, containerId) {
            const container = document.getElementById(containerId);
            container.innerHTML = '';
            
            if (containerId === 'folderFileList') {
                // 获取项目类型
                const projectType = document.getElementById('projectType').value;
                
                // 根据项目类型定义支持的文件类型
                const extensionMap = {
                    'php': ['.php'],
                    'python': ['.py', '.pyw'],
                    'java': ['.java', '.jsp'],
                    'javascript': ['.js', '.jsx', '.ts', '.tsx'],
                    'auto': ['.php', '.java', '.js', '.py', '.jsx', '.ts', '.tsx', '.pyw', '.jsp']
                };
                
                // 获取主要文件类型和辅助文件类型
                const primaryExtensions = extensionMap[projectType] || extensionMap.auto;
                const auxiliaryExtensions = ['.html', '.css', '.json', '.xml', '.yml', '.yaml'];
                
                // 分类文件
                const validFiles = Array.from(files).filter(file => {
                    const ext = '.' + file.name.split('.').pop().toLowerCase();
                    return primaryExtensions.includes(ext);
                });
                
                const auxiliaryFiles = Array.from(files).filter(file => {
                    const ext = '.' + file.name.split('.').pop().toLowerCase();
                    return auxiliaryExtensions.includes(ext);
                });
                
                // 计算跳过的文件数
                const skippedCount = files.length - validFiles.length - auxiliaryFiles.length;
                
                // 显示处理信息
                showProcessingInfo(validFiles, auxiliaryFiles, skippedCount);
                
                // 只有存在有效文件时才启用审计按钮
                document.getElementById('auditBtn').disabled = validFiles.length === 0;
            } else {
                // 对于单文件上传，保持原有逻辑
                Array.from(files).forEach(file => {
                    const item = document.createElement('div');
                    item.className = 'file-list-item';
                    item.innerHTML = `
                        <i class="bi bi-file-earmark-text"></i>
                        ${file.webkitRelativePath || file.name}
                        <small class="text-muted">(${formatFileSize(file.size)})</small>
                    `;
                    container.appendChild(item);
                });
            }
        }

        // 修改审计按钮状态更新函数
        function updateAuditButtonState() {
            const uploadType = document.getElementById('uploadType').value;
            const inputId = uploadType === 'single' ? 'codeFile' : 'codeFolder';
            const input = document.getElementById(inputId);
            
            document.getElementById('auditBtn').disabled = !input || !input.files.length;
        }

        // 格式化文件大小
        function formatFileSize(bytes) {
            if (bytes === 0) return '0 Bytes';
            const k = 1024;
            const sizes = ['Bytes', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }

        // 修改审计函数
        async function startAudit() {
            showLoading();
            const uploadType = document.getElementById('uploadType').value;
            
            try {
                let result;
                if (uploadType === 'single') {
                    const file = document.getElementById('codeFile').files[0];
                    result = await auditSingleFile(file);
                } else {
                    const files = document.getElementById('codeFolder').files;
                    result = await auditFolder(files);
                }
                
                // 确保结果存在且格式正确
                if (!result || typeof result !== 'object') {
                    throw new Error('无效的响应数据');
                }
                
                // 显示结果
                displayAuditResults(result);
            } catch (error) {
                console.error('审计错误:', error);
                alert('审计失败: ' + error.message);
            } finally {
                hideLoading();
            }
        }

        async function auditSingleFile(file) {
            const formData = new FormData();
            formData.append('file', file);
            
            const apiKey = document.getElementById('apiKey').value;
            const apiBase = document.getElementById('apiBase').value;
            
            if (apiKey) formData.append('api_key', apiKey);
            if (apiBase) formData.append('api_base', apiBase);
            
            try {
                const response = await fetch(`${apiUrl}/api/audit`, {
                    method: 'POST',
                    body: formData
                });
                
                if (!response.ok) {
                    throw new Error('审计请求失败');
                }
                
                const result = await response.json();
                return result;
            } catch (error) {
                throw new Error('审计失败: ' + error.message);
            }
        }

        // 修改 auditFolder 函数
        async function auditFolder(files) {
            try {
                const projectType = document.getElementById('projectType').value;
                
                // 根据项目类型定义支持的文件类型
                const extensionMap = {
                    'php': ['.php'],
                    'python': ['.py', '.pyw'],
                    'java': ['.java', '.jsp'],
                    'javascript': ['.js', '.jsx', '.ts', '.tsx'],
                    'auto': ['.php', '.java', '.js', '.py', '.jsx', '.ts', '.tsx', '.pyw', '.jsp']
                };
                
                // 获取主要文件类型和可选的辅助文件类型
                const primaryExtensions = extensionMap[projectType] || extensionMap.auto;
                const auxiliaryExtensions = ['.html', '.css', '.json', '.xml', '.yml', '.yaml'];
                
                // 分类文件
                const validFiles = Array.from(files).filter(file => {
                    const ext = '.' + file.name.split('.').pop().toLowerCase();
                    return primaryExtensions.includes(ext);
                });
                
                const auxiliaryFiles = Array.from(files).filter(file => {
                    const ext = '.' + file.name.split('.').pop().toLowerCase();
                    return auxiliaryExtensions.includes(ext);
                });

                if (validFiles.length === 0) {
                    throw new Error(`未找到支持的源代码文件（支持 ${primaryExtensions.join(', ')}）`);
                }

                // 显示初始进度
                updateProgress(0, validFiles.length, '准备文件...');
                
                // 创建ZIP文件
                const zip = new JSZip();
                
                // 添加主要源代码文件
                for (let i = 0; i < validFiles.length; i++) {
                    const file = validFiles[i];
                    const relativePath = file.webkitRelativePath || file.name;
                    zip.file(relativePath, file);
                    updateProgress(i + 1, validFiles.length, `正在处理: ${relativePath}`);
                }
                
                // 可选：添加辅助文件（配置文件等）
                if (auxiliaryFiles.length > 0) {
                    auxiliaryFiles.forEach(file => {
                        const relativePath = file.webkitRelativePath || file.name;
                        zip.file(relativePath, file);
                    });
                }

                // 显示处理信息，包括主要文件和辅助文件的统计
                showProcessingInfo(validFiles, auxiliaryFiles, files.length - validFiles.length - auxiliaryFiles.length);
                
                // 更新进度显示为压缩阶段
                updateProgress(validFiles.length, validFiles.length, '正在压缩文件...');
                const zipBlob = await zip.generateAsync({ type: 'blob' });
                
                // 准备上传
                const formData = new FormData();
                formData.append('project', new File([zipBlob], 'project.zip'));
                
                const apiKey = document.getElementById('apiKey').value;
                const apiBase = document.getElementById('apiBase').value;
                
                if (apiKey) formData.append('api_key', apiKey);
                if (apiBase) formData.append('api_base', apiBase);
                
                // 更新进度显示为分析阶段
                resetProgress();
                document.getElementById('loadingText').textContent = '正在进行代码分析...';
                document.getElementById('currentFile').textContent = '正在初始化分析...';
                
                const response = await fetch(`${apiUrl}/api/audit/project`, {
                    method: 'POST',
                    body: formData
                });
                
                if (!response.ok) {
                    throw new Error('项目审计失败');
                }
                
                const result = await response.json();
                
                // 验证响应数据结构
                if (!result || typeof result !== 'object') {
                    throw new Error('无效的响应数据');
                }
                
                if (!result.status || !Array.isArray(result.suspicious_files)) {
                    throw new Error('响应数据格式错误');
                }
                
                return result;
            } catch (error) {
                throw new Error('审计失败: ' + error.message);
            }
        }

        // 添加重置进度条函数
        function resetProgress() {
            const progressBar = document.getElementById('progressBar');
            const currentFileText = document.getElementById('currentFile');
            
            progressBar.style.width = '0%';
            progressBar.setAttribute('aria-valuenow', 0);
            progressBar.textContent = '0%';
            currentFileText.textContent = '';
        }

        // 修改更新进度条函数
        function updateProgress(processed, total, message = '') {
            const percentage = Math.round((processed / total) * 100);
            const progressBar = document.getElementById('progressBar');
            const loadingText = document.getElementById('loadingText');
            const currentFileText = document.getElementById('currentFile');
            
            progressBar.style.width = `${percentage}%`;
            progressBar.setAttribute('aria-valuenow', percentage);
            progressBar.textContent = `${percentage}%`;
            
            if (message) {
                currentFileText.textContent = message;
            }
            
            loadingText.textContent = `处理进度：${processed}/${total}`;
        }

        // 更新显示处理信息的函数
        function showProcessingInfo(validFiles, auxiliaryFiles, skippedCount) {
            const container = document.getElementById('folderFileList');
            const projectType = document.getElementById('projectType').value;
            
            container.innerHTML = `
                <div class="alert alert-info">
                    <h6 class="mb-2">文件处理信息：</h6>
                    <p class="mb-1">待审计主要文件数：${validFiles.length}</p>
                    <p class="mb-1">相关辅助文件数：${auxiliaryFiles.length}</p>
                    <p class="mb-1">已跳过文件数：${skippedCount}</p>
                    <p class="mb-0">项目类型：${projectType === 'auto' ? '自动检测' : projectType.toUpperCase()}</p>
                </div>
                <div class="mt-3">
                    <h6>待审计主要文件：</h6>
                    ${validFiles.map(file => `
                        <div class="file-list-item">
                            <i class="bi bi-file-earmark-code"></i>
                            ${file.webkitRelativePath || file.name}
                            <small class="text-muted">(${formatFileSize(file.size)})</small>
                        </div>
                    `).join('')}
                </div>
                ${auxiliaryFiles.length > 0 ? `
                    <div class="mt-3">
                        <h6>相关辅助文件：</h6>
                        ${auxiliaryFiles.map(file => `
                            <div class="file-list-item text-muted">
                                <i class="bi bi-file-earmark"></i>
                                ${file.webkitRelativePath || file.name}
                                <small>(${formatFileSize(file.size)})</small>
                            </div>
                        `).join('')}
                    </div>
                ` : ''}
            `;
        }

        function displayAuditResults(result) {
            const resultsDiv = document.getElementById('results');
            resultsDiv.style.display = 'block';
            resultsDiv.innerHTML = '';

            // 显示总体摘要，添加风险等级对应的颜色
            const summaryCard = document.createElement('div');
            summaryCard.className = 'card mb-4';
            const riskLevelColor = result.summary.risk_level === 'high' ? 'danger' : 
                                  result.summary.risk_level === 'medium' ? 'warning' : 'info';
            
            summaryCard.innerHTML = `
                <div class="card-header bg-${riskLevelColor} text-white">
                    <h5 class="mb-0">审计摘要</h5>
                </div>
                <div class="card-body">
                    <div class="row">
                        <div class="col-md-6">
                            <p><i class="bi bi-check-circle-fill text-${result.status === 'success' ? 'success' : 'danger'}"></i> 
                               状态: ${result.status || '未知'}</p>
                            ${result.message ? `<p><i class="bi bi-info-circle-fill"></i> 消息: ${result.message}</p>` : ''}
                        </div>
                        <div class="col-md-6">
                            <p><i class="bi bi-file-earmark-text"></i> 发现可疑文件数: ${result.suspicious_files?.length || 0}</p>
                            ${result.summary ? `
                                <p><i class="bi bi-exclamation-triangle-fill text-${riskLevelColor}"></i> 
                                   总问题数: ${result.summary.total_issues}</p>
                                <p><i class="bi bi-shield-fill-exclamation"></i> 
                                   风险等级: <span class="badge bg-${riskLevelColor}">${result.summary.risk_level.toUpperCase()}</span></p>
                            ` : ''}
                        </div>
                    </div>
                </div>
            `;
            resultsDiv.appendChild(summaryCard);

            // 显示每个可疑文件的详细信息
            if (result.suspicious_files && Array.isArray(result.suspicious_files)) {
                const accordion = document.createElement('div');
                accordion.className = 'accordion mb-4';
                accordion.id = 'filesAccordion';

                result.suspicious_files.forEach((file, index) => {
                    const fileCard = document.createElement('div');
                    fileCard.className = 'accordion-item';
                    
                    // 安全地访问 AI 验证结果
                    const aiVerification = result.ai_verification?.[file.file_path];
                    const hasHighSeverity = file.issues.some(issue => issue.severity === 'high');
                    
                    fileCard.innerHTML = `
                        <h2 class="accordion-header">
                            <button class="accordion-button ${hasHighSeverity ? 'text-danger' : ''}" type="button" 
                                    data-bs-toggle="collapse" data-bs-target="#collapse${index}">
                                <i class="bi bi-file-earmark-code me-2"></i>
                                ${file.file_path.split('\\').pop()} 
                                ${hasHighSeverity ? '<span class="badge bg-danger ms-2">高危</span>' : ''}
                            </button>
                        </h2>
                        <div id="collapse${index}" class="accordion-collapse collapse ${index === 0 ? 'show' : ''}" 
                             data-bs-parent="#filesAccordion">
                            <div class="accordion-body">
                                <div class="mb-3">
                                    <h6><i class="bi bi-bug"></i> 发现的问题:</h6>
                                    <div class="list-group">
                                        ${file.issues.map(issue => `
                                            <div class="list-group-item">
                                                <div class="d-flex justify-content-between align-items-center">
                                                    <span class="badge bg-${issue.severity === 'high' ? 'danger' : 
                                                          issue.severity === 'medium' ? 'warning' : 'info'} me-2">
                                                        ${issue.severity.toUpperCase()}
                                                    </span>
                                                    <span class="flex-grow-1 ms-2">${issue.description}</span>
                                                </div>
                                                ${issue.line ? `
                                                    <small class="text-muted">
                                                        <i class="bi bi-code-slash"></i> 行号: ${issue.line}
                                                    </small>
                                                ` : ''}
                                            </div>
                                        `).join('')}
                                    </div>
                                </div>
                                
                                ${aiVerification?.ai_analysis?.analysis?.raw_text ? (() => {
                                    try {
                                        const analysis = JSON.parse(aiVerification.ai_analysis.analysis.raw_text);
                                        return `
                                            <div class="mt-4">
                                                <h6><i class="bi bi-robot"></i> AI 分析建议:</h6>
                                                
                                                <!-- 漏洞确认 -->
                                                <div class="alert alert-info">
                                                    <h6 class="alert-heading">
                                                        <i class="bi bi-shield-fill"></i> 漏洞确认
                                                    </h6>
                                                    <hr>
                                                    <p>${analysis.vulnerability_confirmation.dangerous_function.evidence}</p>
                                                    <p><strong>是否误报:</strong> 
                                                        ${analysis.vulnerability_confirmation.dangerous_function.is_false_positive ? '是' : '否'}
                                                    </p>
                                                </div>

                                                <!-- 影响分析 -->
                                                <div class="alert alert-warning">
                                                    <h6 class="alert-heading">
                                                        <i class="bi bi-exclamation-triangle"></i> 影响分析
                                                    </h6>
                                                    <hr>
                                                    <p><strong>严重程度:</strong> ${analysis.impact_analysis.dangerous_function.severity}</p>
                                                    <p><strong>利用条件:</strong> ${analysis.impact_analysis.dangerous_function.exploit_conditions}</p>
                                                    <p><strong>影响范围:</strong> ${analysis.impact_analysis.dangerous_function.impact_scope}</p>
                                                </div>

                                                <!-- 修复建议 -->
                                                <div class="alert alert-success">
                                                    <h6 class="alert-heading">
                                                        <i class="bi bi-tools"></i> 修复建议
                                                    </h6>
                                                    <hr>
                                                    <p><strong>代码级修复:</strong> ${analysis.remediation_suggestions.dangerous_function.code_level_fix}</p>
                                                    <p><strong>安全编码实践:</strong> ${analysis.remediation_suggestions.dangerous_function.secure_coding_practices}</p>
                                                    <p><strong>安全配置建议:</strong> ${analysis.remediation_suggestions.dangerous_function.security_configuration_suggestions}</p>
                                                </div>

                                                <!-- 关联分析 -->
                                                <div class="alert alert-info">
                                                    <h6 class="alert-heading">
                                                        <i class="bi bi-diagram-3"></i> 关联分析
                                                    </h6>
                                                    <hr>
                                                    <p><strong>关联性:</strong> ${analysis.correlation_analysis.dangerous_function.association}</p>
                                                    <p><strong>组合利用:</strong> ${analysis.correlation_analysis.dangerous_function.exploit_combination}</p>
                                                    <p><strong>整体修复策略:</strong> ${analysis.correlation_analysis.dangerous_function.overall_remediation_strategy}</p>
                                                </div>
                                            </div>
                                        `;
                                    } catch (e) {
                                        console.error('解析 AI 分析结果失败:', e);
                                        return `
                                            <div class="alert alert-danger">
                                                <h6 class="alert-heading">AI 分析结果解析失败</h6>
                                                <hr>
                                                <p>错误信息: ${e.message}</p>
                                                <pre class="mt-2">${aiVerification.ai_analysis.analysis.raw_text}</pre>
                                            </div>
                                        `;
                                    }
                                })() : ''}
                            </div>
                        </div>
                    `;
                    
                    accordion.appendChild(fileCard);
                });
                
                resultsDiv.appendChild(accordion);
            }

            // 显示修复建议
            if (result.recommendations?.length > 0) {
                const recommendationsCard = document.createElement('div');
                recommendationsCard.className = 'card mt-4';
                recommendationsCard.innerHTML = `
                    <div class="card-header bg-success text-white">
                        <h5 class="mb-0"><i class="bi bi-tools"></i> 修复建议</h5>
                    </div>
                    <div class="card-body">
                        <div class="list-group">
                            ${result.recommendations.map(rec => `
                                <div class="list-group-item">
                                    <div class="d-flex align-items-center">
                                        <i class="bi bi-file-earmark-text me-2"></i>
                                        <div>
                                            <strong>${rec.file.split('\\').pop()}</strong>
                                            <p class="mb-0 text-muted">${rec.recommendation}</p>
                                        </div>
                                    </div>
                                </div>
                            `).join('')}
                        </div>
                    </div>
                `;
                resultsDiv.appendChild(recommendationsCard);
            }
        }

        function showLoading() {
            document.getElementById('loading').style.display = 'block';
            document.getElementById('results').style.display = 'none';
        }

        function hideLoading() {
            document.getElementById('loading').style.display = 'none';
        }

        // 添加主题切换功能
        function toggleTheme() {
            const body = document.body;
            const themeIcon = document.getElementById('themeIcon');
            const currentTheme = body.getAttribute('data-theme');
            
            if (currentTheme === 'dark') {
                body.removeAttribute('data-theme');
                themeIcon.className = 'bi bi-moon-fill';
                localStorage.setItem('theme', 'light');
            } else {
                body.setAttribute('data-theme', 'dark');
                themeIcon.className = 'bi bi-sun-fill';
                localStorage.setItem('theme', 'dark');
            }
        }

        // 初始化主题
        function initTheme() {
            const savedTheme = localStorage.getItem('theme') || 'light';
            const themeIcon = document.getElementById('themeIcon');
            
            if (savedTheme === 'dark') {
                document.body.setAttribute('data-theme', 'dark');
                themeIcon.className = 'bi bi-sun-fill';
            } else {
                document.body.removeAttribute('data-theme');
                themeIcon.className = 'bi bi-moon-fill';
            }
        }

        // 添加项目类型切换监听
        document.getElementById('projectType').addEventListener('change', function() {
            const uploadType = document.getElementById('uploadType').value;
            if (uploadType === 'folder') {
                const folderInput = document.getElementById('codeFolder');
                if (folderInput.files && folderInput.files.length > 0) {
                    // 重新扫描已选择的文件
                    updateFileList(folderInput.files, 'folderFileList');
                }
            }
        });
    </script>

    <!-- 添加JSZip库 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js"></script>
</body>
</html> 